package jEDF.Montage;

import java.util.*;

import jEDF.EDF.*;
import jEDF.Exceptions.*;
import jEDF.JEDF.*;

/**
 *
 * <p>Titre : jEDF</p>
 * <p>Description : Java European Data Format Viewer and Analyser</p>
 * <p>Author : Nizar Kerkeni</p>
 * <p>Copyright : Copyright (c) 2003-2006</p>
 * <p>Version 2.0</p>
 */

public class Montage implements Cloneable {
    private Vector vectGraphs = new Vector();
    private HashMap hmGraphs = new HashMap();
    private static Montage defaultMontage = null;
    private static Montage presetMontage = null;

    /**
     * @return the default Montage, i.e. the montage containing
     * all the signals found in the currently loaded EDFFile
     */
    public static Montage getDefaultMontage() {
        return (Montage) defaultMontage.clone();
    }

    /**
     * @param polysomnograph the polysomnograp where this montage is to be displayed
     * @param edfFile the EDFFile to read the signals from
     * @return the default montage
     */
    public Montage loadEDFFile(Polysomnograph polysomnograph, EDFFile edfFile) {
        if (edfFile.isItAHypnogramRecord()) {
            return null;
        }

        int nbSignals = edfFile.getNbSignals();

        for (int i = 0; i < nbSignals; i++) {
            if (edfFile.getSignal(i).isEmbeddedHypnogram()) {
                continue;
            }

            JEDFGraph graph = new JEDFGraph(polysomnograph, edfFile.getSignal(i)); //,0);

            vectGraphs.add(graph);
            hmGraphs.put(edfFile.getSignal(i).getLabel(), graph);
        }

        createPresetMontage();

        defaultMontage = this;

        return defaultMontage;
    }


    /**
     * @return an array contening all the signals' names in this montage
     */
    public String[] listAllSignalName() {
        JEDFGraph[] graphs = (JEDFGraph[]) vectGraphs.toArray(new JEDFGraph[vectGraphs.size()]);

        String[] result = new String[graphs.length];

        for (int i = 0; i < graphs.length; i++) {
            result[i] = graphs[i].getSignal().getLabel();
        }

        return result;
    }


    /**
     * @return an array containing all the graphs in this montage
     */
    public JEDFGraph[] getAllGraph() {
        return (JEDFGraph[]) vectGraphs.toArray(new JEDFGraph[vectGraphs.size()]);
    }

    /**
     * @param graph a Graph to be added to this Montage
     */
    public void addGraph(JEDFGraph graph) {
        JEDFGraph graphToBeAdded = (JEDFGraph) graph.clone();
        hmGraphs.put(graph.getSignal().getLabel(), graphToBeAdded);
        vectGraphs.add(graphToBeAdded);
    }


    /**
     * @param i the number of the graph (0..n-1)
     * @return the corresponding Graph
     */
    public JEDFGraph getGraph(int i) {
        return (JEDFGraph) vectGraphs.get(i);
    }

    /**
     * @param graphName the label of the graph
     * @return the wanted graph
     */
    public JEDFGraph getGraph(String graphName) {
        return (JEDFGraph) hmGraphs.get(graphName);
    }

    /**
     * @return the number of signals in this montage
     */
    public int getNbSignals() {
        return vectGraphs.size();
    }

    /**
     * clear this montage, removing all its graphs
     */
    public void clear() {
        vectGraphs.clear();
        hmGraphs.clear();
    }

    private void createPresetMontage() {
        presetMontage = new Montage();

        boolean test = true;

        test = test && hmGraphs.containsKey("C3");
        test = test && hmGraphs.containsKey("A2");
        test = test && hmGraphs.containsKey("C4");
        test = test && hmGraphs.containsKey("A1");

        test = test && hmGraphs.containsKey("EOG1");
        test = test && hmGraphs.containsKey("EOG2");
        test = test && hmGraphs.containsKey("EOG3");

        test = test && hmGraphs.containsKey("EMG1");

        if (test) {
            try {
                EDFBipolarSignal bipolarSignalData;

                bipolarSignalData = new EDFBipolarSignal(
                        (JEDFGraph) hmGraphs.get("C3"), (JEDFGraph) hmGraphs.get("A2"));

                JEDFGraph graph = new JEDFGraph((JEDFGraph) hmGraphs.get("C3"),
                                                bipolarSignalData);
                presetMontage.addGraph(graph);

                bipolarSignalData = new EDFBipolarSignal(
                        (JEDFGraph) hmGraphs.get("C4"), (JEDFGraph) hmGraphs.get("A1"));
                graph = new JEDFGraph((JEDFGraph) hmGraphs.get("C3"), bipolarSignalData);
                presetMontage.addGraph(graph);

                presetMontage.addGraph((JEDFGraph) hmGraphs.get("EOG1"));
                presetMontage.addGraph((JEDFGraph) hmGraphs.get("EOG2"));
                presetMontage.addGraph((JEDFGraph) hmGraphs.get("EOG3"));

                presetMontage.addGraph((JEDFGraph) hmGraphs.get("EMG1"));
            }
            catch (EDFSignalsNotCorrespondingException e) {
                presetMontage = null;
            }
        }
        else {
            presetMontage = null;
        }

    }

    /**
     * @return the preset montage or the default montage if no preset is available
     */
    public static Montage getPresetMontage() {
        if (presetMontage != null) {
            return presetMontage;
        }
        return defaultMontage;
    }

    /**
     * @return whether the default montage is available or not
     */
    public static boolean isPresetAvailable() {
        return presetMontage != null;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#clone()
     */
    public Object clone() {
        Montage montage = new Montage();

        montage.vectGraphs = new Vector();
        montage.hmGraphs = new HashMap();

        Enumeration enu = vectGraphs.elements();
        while (enu.hasMoreElements()) {
            JEDFGraph graph = (JEDFGraph) enu.nextElement();
            montage.vectGraphs.add(graph);
            montage.hmGraphs.put(graph.getSignal().getLabel(), graph);
        }

        return montage;
    }


}
